<template>
  <!--
    父组件以形如:foo="xxx"或者v-bind="{age:12}"传给子组件的属性，但凡没有被子组件的props接收的，都会被扔到子组件的$attrs里去。
    另外，被props指名接收的，都放入子组件的$props里。
  -->
  <el-form
    ref="form"
    :model="form"
    label-position="left"
    label-suffix=":"
    v-bind="$attrs"
    label-width="80px"
  >
    <el-form-item
      v-for="item in formItems"
      :key="item.key"
      :rules="item._rule"
      :prop="item.key"
      :label="item.title"
    >
      <template v-if="item._isShow">
        <!-- component是一个占位符，:is属性可以用来指定要展示的组件名称 -->
        <!-- v-bind的本质是 批量传入props -->
        <!--
            <component v-bind="{a: foo, b: bar, c: baz}" />

            <component
              :a=foo
              :b=bar
              :c=baz
            />
        -->
        <component
          :is="item.type"
          v-model="form[item.key]"
          :options="item.options"
          v-bind="item.props"
        />
      </template>
    </el-form-item>
    <el-form-item
      class="pro-btn"
      v-if="hasControl"
    >
      <el-button @click="submit">{{submitText}}</el-button>
      <el-button @click="reset">{{resetText}}</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
import { computeFormItem } from './core'
import baSelect from '../base-components/ba-select.vue'
export default {
  name: 'proForm',
  components: {
    baSelect
  },
  props: {
    fields: {
      type: Array,
      default: () => [] // 对象或数组的默认值必须从一个工厂函数返回
      // default: function () {
      //   return []
      // }
    },
    hasControl: {
      type: Boolean,
      default: true
    },
    submitText: {
      type: String,
      default: '提交'
    },
    resetText: {
      type: String,
      default: '重置'
    }
  },
  data () {
    return {
      // form: {
      //   username: '李明',
      //   password: '123456'
      // }
      form: this.initForm()
    }
  },
  computed: {
    formItems () {
      // return this.fields
      // console.log('fields', this.fields)
      // 加花括号会出错
      // return this.fields.map(item => {
      //   // console.log('map', item)
      //   computeFormItem(item, this.form)
      // })
      return this.fields.map(item =>
        // console.log('map', item)
        computeFormItem(item, this.form)
      )
    }
  },
  watch: {},
  created () {
    // console.log('this.fields', this.fields)
    // console.log('this.hasControl', this.hasControl)
    // console.log('$attrs', this.$attrs)
  },
  mounted () {},
  methods: {
    initForm () {
      const form = {}
      this.fields.forEach(item => {
        // TODO: 给表单每一项都设置默认值
        form[item.key] = item.defaultValue
      })
      // console.log('initForm', form)
      return form
    },
    // 表单提交
    submit () {
      // this.$emit('submit', this.form)
      this.$refs.form.validate((valid) => {
        // 数据类型处理
        this.fields.forEach(item => {
          // 如果 dataType 被定义
          if (item.dataType) {
            // TODO: 如果字符串值能被完整地转换 Number()将判断是调用parseInt()方法还是调用 parseFloat()方法
            // TODO: 由于Number()函数在转换字符串比较复杂而且不够合理，因此常用parseInt()方法和parseFloat()方法来处理字符串和数值之间的转换。
            // 如果是 int 则强制转换为 int 否则转换为 float 如果是空字符串则转为0
            this.form[item.key] = item.dataType === 'int' ? parseInt(this.form[item.key] || 0) : parseFloat(this.form[item.key] || 0)
            // console.log(this.form[item.key])
            // console.log(typeof this.form[item.key])
            // console.log('isInteger', Number.isInteger(this.form[item.key]))
          }
        })
        this.$emit('submit', this.form, valid)
      })
    },
    // 表单重置
    reset () {
      this.$refs.form.resetFields()
    },
    // 清除校验规则
    clear () {
      this.$refs.form.clearValidate()
    }
  }
}
</script>

<style scoped lang="scss">
// .pro-btn {
//   display: flex;
//   justify-content: space-around;
// }
</style>
